package datamining.algorithms.prefixspan;

import java.util.BitSet;
import java.util.Collection;

import datamining.miner.chain.Extension;
import datamining.miner.enviroment.ThreadEnvironment;
import datamining.miner.general.Embedding;
import datamining.miner.general.ExtendedEmbedding;
import datamining.miner.general.Frequency;
import datamining.miner.general.IndexedSequence;
import datamining.sequence.IndexedItem;
import datamining.sequence.Sequence;

/**
 * <p>
 * 创建于 2012-12-18 下午10:26:14
 * 
 * @author xujinghu (jinghuxu@nudt.edu.cn) <br>
 *         Copyright 2012 xujinghu <br>
 *         Lisence: Apache
 */
public class LazyExtendedEmbedding<ItemType> implements
		ExtendedEmbedding<ItemType> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private Extension<ItemType> ext;//新扩展，其中sequence和fragment均为新的
	private IndexedItem<ItemType> superExtendItem;//延迟扩展项
	PrefixSpanEmbedding<ItemType> cache;//延迟扩展的embedding

	private boolean needsExtension = true;//允许进行扩展一次，扩展之后置为false

	public LazyExtendedEmbedding(Extension<ItemType> ext,
			IndexedItem<ItemType> superExtendItem,
			PrefixSpanEmbedding<ItemType> emb) {
		this.ext = ext;
		this.superExtendItem = superExtendItem;
		this.cache = emb;
	}

	public Embedding<ItemType> extend(Extension<ItemType> ext,
			IndexedItem<ItemType> itemExtend) {
		return get().extend(ext, itemExtend);
	}

	public Frequency frequency() {
		return get().frequency();
	}

	protected Embedding<ItemType> get() {
		// TODO 需要对embedding的扩展实现
		if (needsExtension) {// 只扩展一次
			needsExtension = false;
			cache = cache.clone();// 复制之前待扩展的embedding
			cache.setSubSequence(ext.getFragment().toSequence());// 设置新的embedding的sequence为fragment中的sequence

			boolean isNewSet = (ext.getExtendItem().itemSetIndex != cache
					.getSubSequence().getItemSets().size() - 1);// 判断新扩展项的位置
			cache.getSubSequence().append(
					(ext.getExtendItem().label), isNewSet);// 序列中添加扩展项
			cache.getMap()
					.put(ext.getExtendItem(),
							superExtendItem);// 映射关系中添加新项的映射关系
		}
		return cache;
	}

	/**
	 * @author xujinghu
	 * @date 2012-12-18下午10:43:52
	 * @return 此embedding延迟的扩展
	 */
	public Extension<ItemType> getExtension() {
		return ext;
	}

	public IndexedSequence<ItemType> getIndexedSequence() {
		return get().getIndexedSequence();
	}

	public Sequence<ItemType> getSubSequence() {
		return get().getSubSequence();
	}

	public IndexedItem<ItemType> getSubSequenceItem(
			IndexedItem<ItemType> superItem) {
		return get().getSubSequenceItem(superItem);
	}

	public Sequence<ItemType> getSuperSequence() {
		return get().getSubSequence();
	}

	public IndexedItem<ItemType> getSuperSequenceItem(
			IndexedItem<ItemType> subItem) {
		return get().getSuperSequenceItem(subItem);
	}

	/**
	 * checks if the given Extension can be mapped to this embedding
	 * 
	 * @param ext
	 * @return <code>true</code>, if at least one supergraph edge is
	 *         represented by the given extension
	 */
	public boolean mapExtension(Extension<ItemType> ext) {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean overlaps(Embedding<ItemType> other,
			Collection<ItemType> ignore) {
		return get().overlaps(other, ignore);
	}

	@Override
	public void release(ThreadEnvironment<ItemType> target) {
		// TODO Auto-generated method stub

	}

	@Override
	public int mapExtension(Extension<ItemType> ext, BitSet allowedItems) {
		// TODO Auto-generated method stub
		return 0;
	}

	public String toString() {
		String str = "";
		str += "subSequence = " + ext.getFragment().toSequence() + "\n"
				+ "superSequence = " + cache.getSuperSequence()
				+ "\n";
		return str;
	}
}
